
// 计算任意数字之和
function sum() {
    var sum = 0;
    for (var i = 0; i < arguments.length; i++) {
        sum += arguments[i]
    }
    return sum;
}
// 求任意数中的最小值
function minNum() {
    var min = arguments[0];
    for (var i = 0; i < arguments.length; i++) {
        if (min > arguments[i]) {
            min = arguments[i]
        }
    }
    // console.log(min);
    return min;
}
// 求任意数中的最大值
function maxNum() {
    var max = arguments[0];
    for (var i = 0; i < arguments.length; i++) {
        if (max < arguments[i]) {
            max = arguments[i]
        }
    }
    // console.log(min);
    return max;
}
// 生成一个任意范围内的随机整数
function getRandomNum(a, b) {
    if (a > b) {
        return parseInt(Math.random() * (a - b + 1)) + b
    }
    return parseInt(Math.random() * (b - a + 1)) + a
}

// 封装一个随机颜色（不依赖 getRandomNum(a, b))
function getRandomColor(a) {
    if (a === 16) {
        var str = '0123456789abcdef';
        var res = '';
        for (var i = 0; i < 6; i++) {
            var idx = parseInt(Math.random() * 16);
            res += str[idx];
        }
        return '#' + res;
    }

    var r = parseInt(Math.random() * 256);
    var g = parseInt(Math.random() * 256);
    var b = parseInt(Math.random() * 256);
    return 'rgb(' + r + ',' + g + ',' + b + ')'
}

/* 
    封装一个函数来写事件的兼容
    可变的东西都可以当成函数的参数
    【1】事件源
    【2】事件类型
    【3】事件出来函数
*/
//事件监听  ele对象 type事件类型 fn执行代码函数
function bindEvent(ele, type, fn) {
    // 做兼容判断
    if (ele.addEventListener) {
        ele.addEventListener(type, function () {
            fn();
        })
    } else {
        ele.attachEvent('on' + type, function () {
            fn();
        })
    }
}

//获取元素当前样式 obj:元素对象 name:属性名
function getStyle(obj,name){
    if(window.getComputedStyle){
        return window.getComputedStyle(obj)[name];
    }else{
        return obj.currentStyle[name];
    }
}

//阻止冒泡
function stopMaopao(e){
    if(window.stopPropagation){
        e.stopPropagation();
    }else{
        e.cancelBubble = true;
    }
}

//取消默认事件
function stopMoren(e){
    if(e.preventDefault){
        e.preventDefault();
    }else{
        e.returnValue = false;
    }
}

//获取页面可视化高度
var clientHeight = window.innerHeight? window.innerHeight:document.documentElement.clientHeight;

//scrolltop滚动条高度
// var scrollTop = document.documentElement.scrollTop? document.documentElement.scrollTop:document.body.scrollTop;

//ajax请求
function ajax(){
    if(window.XMLHttpRequest){
        var xhr = new XMLHttpRequest();
    }else{
        var xhr = new ActiveXObject("Microsoft.XMLHTTP");
    }
    return xhr;
}
/* 
    封装获取元素的函数：
    函数的实参形式：
    【1】#id名    表示通过id名获取元素
    【2】.class名 表示通过class名获取元素
    【3】标签名    表示同给标签名获取元素
*/

//根据id名，class名，标签名，获取对应内容
function getEle(ele){
    var str1 = ele.slice(0,1);
    var str2 = ele.slice(1);

    if(str1 == "#"){
        return  document.getElementById(str2);
    }else if(str1 == "."){
        return  document.getElementsByClassName(str2);
    }else{
        return  document.getElementsByTagName(ele);
    }
}

 /* 
    封装动画：
        参数：
        【1】谁要做动画
        【2】参数动画的属性
        【3】目标值

        当这个对象要执行多属性动画
        多个属性执行的动画
        属性跟目标值是配套的，把他们方在一起
        {属性:目标值,属性1：目标值1}

        怎么知道动画执行结束（函数里面的素有定时器都执行结束才表示动画结束）
   */
function move(ele,obj,callback){
    //记录定时器个数
    let timeLen = 0;
    for(const key in obj){
        //循环一次创建一个定时器，timeLen++
        timeLen++;
        //定时器绑定在ele元素上
        ele[key] = setInterval(() => {
            
            let curStyle;
            if(key === "opacity"){
                curStyle=getStyle(ele,key) * 100;
            }else{
                curStyle=parseInt(getStyle(ele,key));
            }
            //目标值 - 元素当前值 / 一个系数
            let speed = (obj[key] - curStyle) / 5;

            speed = speed > 0? Math.ceil(speed) : Math.floor(speed);

            if(curStyle === obj[key]){
                clearInterval(ele[key]);
                //每清除一个定时器，timeLen--
                timeLen--
                if(timeLen === 0){
                    //如果不需要回调，就不用回调
                    callback && callback();
                }
            }else{
                if(key === "opacity"){
                    ele.style[key] = (speed + curStyle) / 100;
                }else{
                    ele.style[key] = speed + curStyle + "px"
                }
            }
        },20) 
    }
    
}

//放大镜
class Enlarge{
    constructor(ele){
        this.ele = ele;
        //获取页面显示图片容器
        this.show = this.ele.querySelector(".show");
        //获取遮罩层
        this.mask = this.show.querySelector(".mask");
        //获取小图片容器
        this.list = this.ele.querySelector(".list");
        this.p = this.list.querySelectorAll("p");
        //获取放大镜容器
        this.enlarge = this.ele.querySelector(".enlarge");
        
        this.init();
        this.change()
    }
    init(){
        //添加mask在show里移动事件
        this.show.addEventListener("mouseover",() =>{
            this.mask.style.display = this.enlarge.style.display = "block";
           
            this.setStyle();
            this. move();
        })
         //添加mask在show里移出事件
         this.show.addEventListener("mouseout",() =>{
            this.mask.style.display = this.enlarge.style.display = "none";
        })
        
    }
    setStyle(){
        //分别求出遮罩层，图片容器show，背景图的尺寸, 设置放大镜容器宽高
        //求出遮罩层mask的尺寸(宽，高)
        this.maskWidth = this.mask.offsetWidth;
        this.maskHeight = this.mask.offsetHeight;

        //求出图片容器show的尺寸(宽，高)
        this.showWidth = this.show.offsetWidth;
        this.showHeight = this.show.offsetHeight;

        //求出enlarge内背景图的尺寸(宽，高)
        let red = window.getComputedStyle(this.enlarge).backgroundSize.split(" ");
        this.W = parseInt(red[0]);
        this.H = parseInt(red[1]);

        //求出放大镜容器enlarge的尺寸(宽，高)    mask尺寸 ：show尺寸  =  放大镜容器尺寸 :  放大镜背景图尺寸
        this.enlargeWidth = this.maskWidth / this.showWidth *  this.W + "px";
        this.enlargeHeight = this.maskHeight / this.showHeight *  this.H + "px";
        
    }
    move(){
        //鼠标移动mask跟着在show内移动
        this.show.addEventListener("mousemove",e =>{
            
            let x = e.clientX - this.ele.offsetLeft - this.maskWidth / 2;
            let y = e.clientY - this.ele.offsetTop - this.maskHeight / 2;

            if( x <= 0){
                x = 0;
            }
            if( y <= 0){
                y = 0;
            }   
            if( x >= this.showWidth - this.maskWidth){
                x = this.showWidth - this.maskWidth
            }
            if( y >= this.showHeight - this.maskHeight){
                y = this.showHeight - this.maskHeight
            }

            this.mask.style.left = x + "px";
            this.mask.style.top = y + "px";

             //背景图的移动距离 = 遮罩层的移动距离  / show盒子的尺寸  * 背景图的尺寸

            let f1 = x / this.showWidth *  this.W;
            let f2 = y / this.showHeight *  this.H;
            this.enlarge.style.backgroundPosition = `${-f1}px  ${-f2}px`;
        })
     }
    change(){
        let _this = this;
        for(var i=0;i<_this.p.length;i++){

            _this.p[i].onclick = function(e){

                for(var j=0;j<_this.p.length;j++){
                   _this.p[j].classList.remove("active");
                }
                this.classList.add("active");

                //获取show里的img
                let img = _this.show.querySelector("img");
                //替换show里面的图片
                img.setAttribute("src",e.target.getAttribute("img1"));
                //替换enlarge里面的图片
                _this.enlarge.style.backgroundImage = `url(${e.target.getAttribute("imgBig")})`;

            }
        }
    }

}

/**
 * 获取cookie  key ->储存的cookie的名称
 * 注：key 为字符串，必须加引号
 */
function getCookie (key){
    var str = document.cookie;
    //拆分为数组
    str = str.split("; ")
    //定义对象
    var obj={};

    str.forEach(item =>{
        //用=把key和value拆开成另一个数组
        let arr = item.split("=");
        //对象中数组的第0个等于第一个值
        obj[arr[0]] = decodeURIComponent(arr[1]);
    })
    // 从对象里找到key的属性值
    return obj[key];
}
/**
 * 储存cookie  
 * key   ->储存的cookie的名称
 * value ->储存的cookie的值
 * obj   ->存入时间和路径,可选参数，制定存cookie的一些选项，比如 { expires: 7, path: '/'}，存一条7天过期，根目录的cookie
 */
function setCookie(key,value,obj){
    let str = `${key} = ${encodeURIComponent(value)}`;
    //判断是否传了obj
    if(obj){
        //如果传入延长时间
        if(obj.expires){
            var date = new Date();
            date.setDate(date.getDate() + obj.expires)
            str += `;expires=${date.toUTCString()}`;
        }
        //如果存入保存路径
        if(obj.path){
            str += `;path=${obj.path}`;
        }
    }
    document.cookie = str;    
}
/**
 * get方法
 * 参数一：url
 * 参数二：obj 要添加的数据，是一个对象
 * 参数三：fn 方法
 * 参数四：默认 true 转换JOSN.parse格式，传入false则不转换
 */
function get(url,obj,fn,isJson=true){
  
   //如果obj存在，则提取obj对象数据
   if(obj){
        url += "?";
        for(let key in obj){
            url += `${key}=${obj[key]}&`;   
        }
        // 在拼接完成以后最后回多出一个&
        url = url.slice(0,-1);
    }
  
   //1.获取对象
   const xhr = new XMLHttpRequest();
   //2.打开链接
   xhr.open('get',url);
   //3.发送请求
   xhr.send();
   //4.监听状态改变事件
   xhr.onreadystatechange = function(){
        //5.判断状态值和状态码
        if(xhr.readyState === 4 && xhr.status === 200){

        //6.如果isJson为true则转换为json格式
        const res = isJson?JSON.parse(xhr.responseText):xhr.responseText

        //如果有fn,则执行
        fn && fn(res);
    }
   }
}

/**
 * post方法
 * 参数一：url
 * 参数二：obj 要添加的数据，是一个对象
 * 参数三：fn 方法
 * 参数四：默认 true 转换JOSN.parse格式，传入false则不转换
 */
function post(url,obj,fn,isJson=true){
    var str = ''
    if (obj) {
      for (var key in obj) {
        str += `${key}=${obj[key]}&`
      }
      str = str.slice(0, -1)
    }
   
    //获取对象
    const xhr = new XMLHttpRequest();
    //打开链接
    xhr.open('post',url);
    //设置头部
    xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
    //发送请求
    xhr.send(str);
    //监听状态改变事件
    xhr.onreadystatechange = function(){
         //判断状态值和状态码
         if(xhr.readyState === 4 && xhr.status === 200){
 
         //如果isJson为true则转换为json格式
         const res = isJson?JSON.parse(xhr.responseText):xhr.responseText
 
         //如果有fn,则执行
         fn && fn(res);
     }
    }
 }

 /**
  * ajax script方法
  * 参数一   url 地址
  * 参数二   cb  回调函数（这个函数必须是全局函数）
  * 参数三   obj 其他参数
  */
 function ajaxSrc(url,cb,obj){
    //拼接字符串url,cb,obj 保存在str
    url += `?cb=${cb}`;
    //如果obj存在，则提取obj对象数据
    if(obj){
        for(var key in obj){
            url += `&${key}=${obj[key]}`;   
        }
    }
    
    var script = document.createElement("script");
    let body = document.body;
    script.src = url;
    //添加script
    body.appendChild(script);
    //获取后移除script
    body.removeChild(script);  
 }
 /**
  * Promise方法
  * 参数一   url 地址
  * 参数二   obj 其他参数
  * 参数三   isJson 默认 true 转换JOSN.parse格式，传入false则不转换
  */
 function prom(url,obj,isJson = true){
    //如果obj存在，则提取obj对象数据
    if(obj){
        url += '?'
        for(var key in obj){
            url += `${key}=${obj[key]}&`;   
        }
        url = url.slice(0, -1)
    }
    return new Promise((resolve, reject) => {
        var xhr = new XMLHttpRequest()
        xhr.open('get', url)
        xhr.send()
        xhr.onreadystatechange = function () {
          if (xhr.readyState === 4) {
            if (xhr.status === 200) {
              resolve(isJson ? JSON.parse(xhr.responseText) : xhr.responseText)
            } else {
              reject()
            }
          }
        }
    })
 }

